/**
 * Copyright (c) 2011 Tomi Paananen.
 *
 * Part of Quick Gestures engine library.
 */

// Own header
#include "storagethread.h"

// Qt includes
#include <QFile>
#include <QUrl>

// qgengine includes
#include "processingstoragemgr.h"
#include "gesture.h"
#include "qgtrace.h"


/*!
  \class StorageThread
  \brief Threaded storage interface for loading and saving gesture sets.
*/


/*!
  Constructor.
*/
StorageThread::StorageThread(QObject *parent /* = 0 */)
    : QThread(parent),
      m_manager(0),
      m_state(Idle),
      m_doCancel(false)
{
}


/*!
  Destructor.
*/
StorageThread::~StorageThread()
{
    delete m_manager;
}


/*!
  Loads gestures from \a filepath.
*/
void StorageThread::load(const QString &filepath)
{
    DEBUG_INFO(filepath);

    if (m_state != Idle || isRunning()) {
        DEBUG_INFO("The thread is busy!");
        emit failed(QGEngine::ThreadBusy);
        return;
    }

    m_filepath = filepath;
    setState(Loading);
    start();
}


/*!
  For convenience.
*/
void StorageThread::loadByUrl(const QUrl &url)
{
    load(url.toLocalFile());
}


/*!
  Saves \a gestureSet into \a filepath.
*/
void StorageThread::save(const QString &filepath, QList<Gesture*> &gestureSet)
{
    DEBUG_INFO("Will try to save" << gestureSet.count()
               << "gestures into" << filepath);

    if (m_state != Idle || isRunning()) {
        DEBUG_INFO("The thread is busy!");
        emit failed(QGEngine::ThreadBusy);
        return;
    }

    m_filepath = filepath;
    m_gestureSet.clear();
    m_gestureSet += gestureSet;
    setState(Saving);
    start();
}


/*!
  For convenience.
  Saves \a gestureSet into \a url.
*/
void StorageThread::saveByUrl(const QUrl &url, QList<Gesture*> &gestureSet)
{
    DEBUG_INFO(url.toLocalFile());
    save(url.toLocalFile(), gestureSet);
}


/*!
  Returns the state of the thead.
*/
int StorageThread::state() const
{
    return (int)m_state;
}


/*!
  Appends the loaded gestures into \a gestureSet and clears the internal list.
  Returns the number of appended gestures.
*/
int StorageThread::getGestures(QList<Gesture*> &gestureSet)
{
    const int count(m_gestureSet.count());

    if (count) {
        gestureSet += m_gestureSet;
    }

    m_gestureSet.clear();

    return count;
}


/*!
  Returns the storage manager instance.
*/
StorageManager *StorageThread::storageManager() const
{
    return m_manager;
}


/*!
  From QThread.

  Loads/saves gesture depending on the internal state.
*/
void StorageThread::run()
{
    m_manager = new ProcessingStorageMgr();

    connect(m_manager, SIGNAL(gestureProcessed(Gesture*)),
            this, SIGNAL(gestureLoaded(Gesture*)));
    connect(m_manager, SIGNAL(progress(int)),
            this, SIGNAL(progress(int)));

    int error(QGEngine::NoError);

    if (m_state == Loading) {
        error = m_manager->load(m_filepath);

        if (error != QGEngine::NoError) {
            emit failed(error);
        }

        m_manager->getGestures(m_gestureSet);
    }
    else if (m_state == Saving) {
        error = m_manager->save(m_filepath, m_gestureSet);

        if (error != QGEngine::NoError) {
            emit failed(error);
        }

        m_gestureSet.clear();
    }

    if (m_doCancel) {
        // Clear the internal list and emit the signal.
        m_gestureSet.clear();
        emit cancelled();
        m_doCancel = false;
    }

    delete m_manager;
    m_manager = 0;

    setState(Idle);
}


/*!
  Sets the state as \a state and notifies observers by emitting stateChanged()
  signal.
*/
void StorageThread::setState(StorageStates state)
{
    m_state = state;
    emit stateChanged((int)m_state);
}


/*!
  Cancels the ongoing operation.
*/
void StorageThread::cancel()
{
    if (m_state != Idle) {
        m_doCancel = true;
    }
}


// End of file.
